package handle

import (
	"encoding/json"
	"gitee.com/crack007/goose"
	"gitee.com/crack007/goose/core/ws"
	"gitee.com/crack007/goose/log"
	"github.com/crack007/go-im/src/common/component"
	"github.com/crack007/go-im/src/common/config"
	"github.com/crack007/go-im/src/common/constant"
	"github.com/crack007/go-im/src/common/model"
	"github.com/crack007/go-im/src/common/service"
	"net/url"
)

type UserSessionHandle struct {
	ws.DefaultSessionHandle
	userModel         *model.UserModel
	timeoutCount      uint
	idleTimeoutConfig uint
	MsgType           int
	sessionId         int64
}

func (d *UserSessionHandle) OnHandshake() bool {
	token, _ := d.DefaultSessionHandle.Session.Ctx.GetQuery("token")
	if token == "" {
		return false
	}
	jwtToken, err := url.QueryUnescape(token)
	if err != nil {
		return false
	}
	payloadModel, err := component.Jwt.Parse(jwtToken)
	if err != nil {
		return false
	}
	d.userModel = model.NewUserModel()
	err = json.Unmarshal([]byte(payloadModel.Data), d.userModel)
	if err != nil {
		return false
	}
	d.sessionId = int64(d.userModel.Id)
	d.userModel.NodeName = config.GetNodeConfig().NodeName
	d.Session.Tag = constant.SESSION_USER
	d.idleTimeoutConfig = config.WsConfig.IdleCount
	return true
}

func (d *UserSessionHandle) OnConnect() {
	goose.GetLogger().Debug("用户上线了, id=%d nickname=%s", d.userModel.Id, d.userModel.Nickname)
	service.UserService.UserOnline(d.userModel)
}

func (d *UserSessionHandle) OnMessage(wsPackage *ws.WsPackage) {
	d.timeoutCount = 0
	d.MsgType = wsPackage.MessageType
}

func (d *UserSessionHandle) OnClose(err error) {
	d.DefaultSessionHandle.OnClose(err)
	if d.userModel != nil {
		service.UserService.UserOffline(d.userModel)
	}
}

func (d *UserSessionHandle) OnIdleTimeout() {
	d.timeoutCount++
	log.GetLogger().Debug("[%d] Session onIdleTimeout %d 次", d.Session.SessionId, d.timeoutCount)
	if d.idleTimeoutConfig > 0 && d.timeoutCount > d.idleTimeoutConfig {
		d.Session.Close()
	}
}
func (d *UserSessionHandle) GetSessionId() int64 {
	return d.sessionId
}

func (d *UserSessionHandle) OnConflict(newSession *ws.Session) *ws.Session {
	return newSession
}
